#include <stdint.h>
#include "../fe8.h"
#include "chap_type.h"

typedef struct{ //第一章 0x8a5a760  rwatch *(int*)(0x8a5a760+4)
    // union{
	//     void		*u0_;				//基于转向事件?
    //     struct EventProc * event;
    // };
    // union
    // {
    //     void		*u4_;				//基于人物事件
    //     struct EventProc * u4_event;
    // };

    // union{
	//     void		*u8_;				//基于位置事件  移动到目标位置时触发
    //     struct EventProc * u8_event;
    // };

    //条件触发事件
    void		*u0_;				//基于转向事件?
    //条件触发事件
    void		*u4_;				//基于人物事件
    //条件触发事件
    void		*u8_;				//基于位置事件  移动到目标位置时触发,(未待机)
	//条件触发事件
    void		*uC_;				//杂项事件?,(待机时触发,)
	//条件触发事件
    void		*u10_;				//未知,显示攻击范围时触发
	//条件触发事件
    void		*u14_;				//同上, 移动开始(确定移动位置)
	//条件触发事件
    void		*u18_;				//同上，移动结束(移动到指定位置，准备显示菜单时)
	//函数指针数据
    void		*u1C_;				//教程?
	//数据?
    /*
    (撤退,中断时)时触发，指针的数据，为6个字节
    80378D8 函数处理这个指针数据
    [+0]    类型，如果为0，则退出
            1,  8037A9C([+1],[+2],[+3])

            4,  802E24C([+1],[+2],[+4],[+5])

    */
    void		*u20_;				//陷阱?
    //数据
    /*
    撤退,中断时触发一次,跟u20_数据是一样的
    */
	void		*u24_;				//陷阱?
    //
	void		*u28_;				//单位?
    //
	void		*u2C_;				//单位?一般和上一个相同
	uint32_t 	u30_;			//基本都为0
	uint32_t 	u34_;			//基本都为0
	uint32_t 	u38_;			//基本都为0
	uint32_t 	u3C_;			//基本都为0
	uint32_t 	u40_;			//基本都为0
	uint32_t 	u44_;			//基本都为0
	void		*u48_;				//关卡开始时的事件
	void		*u4C_;				//关卡结束时事件
}ChapterEvent;


typedef struct EventProc{
    uint16_t    type;        //事件标志
                                //根据8A5A618 + (type*8)        获得执行事件判断的函数
                                //根据8A5A618 + (type*8) + 4    获得执行事件的大小 ,大小*4 得到结构体的大小
                                    //如1，表示RoundTurn 结构大小为4。为2时，则结构大小为8，为3时，结构大小为12
                            /*
都为函数指针
参数1为事件event

type=2
    arg[0] & 0xff:
        如果202BCEC[0x10]小于arg[0] & 0xff，则返回0
    arg[0] >> 0x8:
        如果arg[0]==0时，(arg[0]>>8) = arg[0] &0xff
        如果202BCEC[0x10]大于arg[0] >> 0x8,则返回0
    arg[1]:
         如果202BCEC[0xf]不等于arg[1]，则返回0

    相当于
        202BCEC[0xf]必须等于arg[1],(arg[0] >> 0x8)>=202BCEC[0x10]>=(arg[0] & 0xff)

    202BCEC[0xf] & 0x80 为敌方回合
    202BCEC[0x10] 为回合数
    arg[1] 为回合条件
    arg[0]&0xff 为最低回合条件
    arg[0]>>8   为最高回合条件

type=1
    arg0 = *(uint32*)arg
    arg0 必须不为0，且不等于100
        小于100时，获得3005260 位偏移值
        大于100时，arg0 -= 100,获得3005240位偏移值

    如果0x3005240,0x3005260 事件标志状态未处理，则执行
        跟RoundTurn->flg类似

        针对标志的定义，
            0,      表示一直执行
            2,      主角死亡
            0x65    BOSS死亡


type=3
    事件长度是0x10
    arg0 = arg[0]&0xff
    arg1 = arg[0]>>8
    arg2 = arg[2]
    arg3 = arg[3]
    如果arg2等于2或等于1时，返回0
    arg3等于3时，
        判断0x3005240,0x3005260 偏移arg[2]事件标志状态，如果未设置，则返回0

    如果event[0x1a]于arg0,获得arg0为空，
        并且arg2等于event[0x1b]
        返回1
    一般用于对话处理
    arg0 为角色id 1
    arg1 为角色id 2
    arg2 为0 ,
    arg3 为0 , 如果arg2为3时，判断0x3005240,0x3005260 偏移arg3的位值，如果为0则返回0


type=4
    事件长度为0x10
    arg0 = arg[0]&0xff
    arg1 = arg[0]>>8
    arg2 = (uint32_t)arg[2]
    arg2为函数指针，执行arg2，如果返回0，则事件返回0
    如果arg0不为空，且event[0x1a]  返回0
    如果arg1不等于event[0x1b]返回0

    一般也是两个单位间的事件，但条件额外添加arg2函数指针执行返回值

type=5
    事件长度为0xc
    处理村庄被摧毁?,如果type=6 后尾不跟着type=5 时，不会摧毁村庄
    "占领"
        event = 1
        arg[0] & 0xff   X坐标
        arg[0] >> 8     Y坐标
        arg[1] = 0x11
    "被盗贼摧毁"
        event = 1
        arg[0] & 0xff   X坐标
        arg[0] >> 8     Y坐标
        arg[1] = 0x20
    // arg0 = arg[0]&0xff
    // arg1 = arg[0]>>8
    // 如果arg0不等于event[0x18] 返回0
    // 如果arg1不等于event[0x19] 返回0


type=6
    事件长度0xc
    村庄访问
        地址8a5a95c (第二章)
    arg[0] & 0xff   为坐标X
    arg[0] >> 0x8   为坐标Y
    arg[1] 一般为   0x0010
    该事件条件后，一般会跟着type5 事件条件

type=7
    事件长度为0xc
    打开宝箱
    arg0 = arg[0]&0xff
    arg1 = arg[0]>>8
    如果arg0不等于event[0x18] 返回0
    如果arg1不等于event[0x19] 返回0
    event       为物品ID，不是事件
    arg[0] & 0xff   为坐标X
    arg[0] >> 0x8   为坐标Y
    arg[1]
        0x14    宝箱
        0x18    秘密商店
        0x17    道具店
        0x16    武器店



type=8
    开门
    arg0 = (uint32_t)arg[0]
    arg1 = (arg0&0xff00) >> 8
    arg2 = (arg0&0xff0000) >> 16
    arg3 = arg0>>24
    如果arg1不等于event[0x18] 返回0
    如果arg2不等于event[0x19] 返回0
    arg[0] & 0xff   为坐标X
    arg[0] >> 0x8   为坐标Y
    标识为0
    event 需要等于1,如果为0，则开不了门，如果为2，则卡机
    arg[1] 为 0x12(开门,如果不是0x12则不显示开门)


type=9
    arg0 = (uint32_t)arg[0]
    arg1 = (arg0&0xff)
    arg2 = (arg0&0xff0000) >> 16
    arg3 = arg0>>24
    如果arg1不等于event[0x18] 返回0
    如果arg2不等于event[0x19] 返回0

type=0xa
    arg0 = arg[0]&0xff
    arg1 = arg[0]>>8
    如果arg0不等于event[0x18] 返回0
    如果arg1不等于event[0x19] 返回0
    如果arg[1]等于24时，并且
        sub_8016DD4(0x3004DF0[0],0x72)等于-1
        返回0

type=0xb
    arg0 = 选择角色的X坐标
    arg1 = 选择角色的Y坐标
    arg2 = arg[0]&0xff
    arg3 = (unsigned __int16)((uint32_t)arg[0] & 0xFF00) << 16 >> 24;
    arg4 = ((uint32_t)arg[0] & 0xFF0000) << 8 >> 24;
    arg5 = (uint32_t)arg[0] >> 24;
    如果arg1小于arg2或者大于arg5 ，返回0
        并且 arg1大于arg2获得小于arg5.
        就是在等级范围内，没有顺序

    X在 [0x8] 和 [0xb] 范围内
    Y在 [0x9] 和 [0xa] 范围内

type=0xc
    直接返回0

type=0xd
    直接返回0

type=0xe
    (uint32_t)arg[0] 为函数,
    执行arg[0] 如果，返回1，则返回1

type=0xf
    arg0 为flg
    arg1 为arg[2]
    判断0x3005240,0x3005260 偏移arg0事件标志状态,如果不为0
        或者判断0x3005240,0x3005260 偏移arg1事件标志状态,如果为0
        则返回0

type=0x10
    同上

                            */
    uint16_t    flg;        // 0表示无条件,大于1且小于99，则相对0x3005260的位偏移的位值
                                //大于101时，减去101，相对0x3005240的位偏移位值
    void*       event;
    uint16_t    arg[2];
}EventProc;

#include "../hack/chapter_def.h"

const ChapterEvent const chapter_event_data[0x100] = {
    //[0] = {0,0,0,0,.u48_ = 234},
#include "../hack/chapter.h"
//[0] = {0,0,0,0,.u48_ = 0x08A60D20},
    //[0].u48_ = 20,
};

const ChapterEvent * const chapter_event[0x100] = {
    //[0] = chapter_event_data + 1,
    [0 ... 0xFF] = 0,
    [0] = chapter_event_data + 0,
    //[0].u48_ = 20,
};

#if 1

void H80345B8_(uint32_t r0,uint32_t r1){
    asm("mov r0,r0\n");
    asm("JMP80345B8_r1:\n");
    asm("mov r1,lr\n");
    asm("b _80345B8_\n");
}

ChapterEvent * _80345B8_(uint32_t r0,uint32_t r1){
#else
ChapterEvent * JMP80345B8_r1(uint32_t r0){
    uint32_t r1;
#endif
    #ifndef NHACK
    #if 0
    if(r1==0x08015407   //章节开始
    //&&1
    ||r1==(0x808636C+1) //人物位置事件      u8_
    ||r1==(0x8086260+1) //角色事件(对话)    u4_
    ||r1==(0x8086206+1) //回合跳转时触发    u0_
    ||r1==(0x808665E +1) //待机时触发
    )
    #endif
    {
        if(chapter_event[r0]){
            return chapter_event[r0];
        }
    }
    #endif
    if(r0==127){
        return (ChapterEvent*)(*(uint32_t**)(0x8A9CA60))[2];
    }
    else{
        ChapterEvent * *ptr = (ChapterEvent **)0x8907BC8;
        return ptr[
            *(uint8_t*)(CALLT(0x8034520,r0) + 0x74)
        ];
    }
}

/*
typedef struct{
    void* pal;
    void* tile1;
    void* tile2;
    void* tileSet;
    void* mapData;
    void* event;

    void* image1;
    void* image2;
}ChapterData;
*/

extern const ChapterData chapterData[0x100] = {

[0].mapData = (void*)(const u16[]){

//标志和大小
0|(48<<8),
304>>8,
//地图数据开始

(15)|(10<<0x8),
0x18c,
0xf40,0xeb8,0xf44,0xb80,0x18c,0x18c,0x18c,0x5c,0x774,0x76c,0x770,0xe0,0x314,0x5c,0x18c,0xf34,
0xf38,0xf3c,0xa90,0x18c,0x18c,0x18c,0xc3c,0x54,0x7f4,0x7f8,0x8f4,0xd8,0xe4,0x18c,0xfb4,0xfb8,
0xfbc,0x18c,0xb80,0x18c,0xe90,0x18c,0x18c,0x5c,0x778,0x76c,0x7f8,0x7f4,0x18c,0x18c,0x398,0x31c,
0x18c,0xc00,0xa94,0x128,0x12c,0x18c,0xa94,0x5c,0x770,0x774,0x58,0xa0c,0x18c,0x18c,0x3b8,0x22c,
0x18c,0x230,0x120,0x124,0xa8c,0xc90,0x18c,0x64,0x68,0x18c,0xa8c,0xb40,0x118,0x11c,0x18c,0x18c,
0x238,0x98,0x98,0x21c,0x18c,0xb40,0x18c,0x18c,0x318,0xa04,0xb0,0x18,0x18,0x1b4,0xc38,0x2b0,
0x298,0x98,0x18,0x224,0x18c,0x18c,0xc90,0x59c,0xa84,0x18c,0x238,0x19c,0x18c,0x93c,0xa2c,0xe90,
0x198,0x19c,0x2b4,0x318,0x41c,0x42c,0x18c,0x230,0x218,0x23c,0x18c,0x93c,0x82c,0x58c,0x8b4,0x944,
0x18c,0x318,0x644,0x6c4,0x324,0x418,0x18,0x18,0x29c,0x7b4,0x830,0x70c,0x820,0x6a4,0xb38,0xb1c,
0x4a0,0x6c4,0x644,0x6c4,0x644,
},

[0].tile1 = (void*)0x08188888,
[0].tile2 = (void*)0x00000000,
[0].pal = (void*)0x0819E5AC,
[0].tileSet = (void*)0x0819B198,
#include "../hack/map_data.h"

};

static const  u32 * const chap_pointers = 0x8907BC8;
//调色板
void JMP801964C_r2(){
    s8 *p = (void*)0x202BCEC;
    u8 *pp = CALLT(0x8034520,p[0xE]);
    void *d= chap_pointers[pp[6]];
    #if 1
    if(chapterData[p[0xE]].pal)
        d = chapterData[p[0xE]].pal;
    #endif
    CALLT(0x8000D68,d,192,320);
}

//地图数据
u32 JMP8034548_r1(u8 a1){
    #if 1
    if(chapterData[a1].mapData){
        return chapterData[a1].mapData;
    }
    #endif
    if(a1==0x7f){
        u32 v1,v2;
        v1 = CALLT(0x80AB588);
        v2 = CALLT(0x80AB5A8);
        void (*v3)() = *(void**)0x03006790;
        v3(v1,0x2020188,v2);
        return 0x2020188;
    }
    else{
        u8 *p = CALLT(0x8034520,a1);
        return chap_pointers[p[8]];
    }
}

//
void JMP8030B90_r1(){
    //L
    u32 v0 = CALLT(0x8002DEC,0x85C5D98);
    if(v0){
        u8 x = ((u8*)0x202BCEC)[0xE];
        u8 *p = CALLT(0x8034520,x);
        u32 v1 = chap_pointers[p[10]];
        #if 1
        if(chapterData[x].image2){
            v1 = (u32)chapterData[x].image2;
        }
        #endif
        ((u32*)(v0+0x3c))[0] = v1;
        ((u32*)(v0+0x38))[0] = v1;
    }
}

//关卡名称，在选取存档时显示
void JMP8030044_r2(u32 a1){
    //L
    *(u16*)(a1+0x34) = 0;
    *(u16*)(a1+0x36) = 0;
    u8* p = CALLT(0x8034520,((u8*)0x202BCEC)[0xE]);
    u32 v2 = chap_pointers[p[9]];
#if 1
    if(chapterData[a1&0xff].image1){
        v2 = (u32)chapterData[a1&0xff].image1;
    }
#endif
    *(u32*)(a1+0x30) = v2;
    *(u32*)(a1+0x2C) = v2;
    p = CALLT(0x8034520,((u8*)0x202BCEC)[0xE]);
    v2 = chap_pointers[p[10]];
#if 1
    if(chapterData[a1&0xff].image2){
        v2 = (u32)chapterData[a1&0xff].image2;
    }
#endif
    *(u32*)(a1+0x3C) = v2;
    *(u32*)(a1+0x38) = v2;
}

//tile 层数据
u32 JMP80195E4_r1(int a1){
    //L
    u8* p =CALLT(0x8034520,a1);
#if 0
    sub_8013008(level_pointers[p[4]],0x6008000);
    if(level_pointers[p[5]]){
        p = sub_8034520(a1);
        sub_8013008(level_pointers[p[5]],0x600C000);
    }
    p =sub_8034520(a1);
    sub_8000D68(level_pointers[p[6]],192,320);

#else
    void *d1,*d2,*d3;
    d1 = (void*)chap_pointers[p[4]];
    if(chapterData[a1&0xff].tile1){
        d1 = chapterData[a1&0xff].tile1;
    }
    CALLT(0x8013008,d1,0x6008000);
    if(chapterData[a1&0xff].tile2){
        d2 = chapterData[a1&0xff].tile2;
    }
    if(!d2){
        p = CALLT(0x8034520,a1);
        d2 = chap_pointers[p[5]];
    }
    if(d2){
        CALLT(0x8013008,d2,0x600C000);
    }

    d3 = (void*)chap_pointers[p[6]];
    if(chapterData[a1&0xff].pal){
        d3 = chapterData[a1&0xff].pal;
    }
    CALLT(0x8000D68,d3,192,320);
#endif
}

void JMP8019584_r2(int a1,int a2){
    //tileSet层，设置
    //L
    u32 v4 = CALLT(0x8034548,a2);
    CALLT(0x8013008,(void*)v4,(void*)a1);
    s16* v2= (void*)0x202E4D0;
    v2[0] = *(u8*)a1;
    v2[1] = *(u8*)(a1+1);
    u8* p =CALLT(0x8034520,a2);
    void* d = chap_pointers[p[7]];
#if 1
    if(chapterData[a2&0xff].tileSet){
        d = chapterData[a2&0xff].tileSet;
    }
#endif
    CALLT(0x8013008,d,0x2030B88);
    s16 *v3 = (void*)(0x202BCAC+0x28);
    v3[0] = (v2[0]<<4) - 240;
    v3[1] = (v2[1]<<4) - 160;
}
